package com.rbcs.budget.webapp;

import java.util.Calendar;
import java.util.Date;
import java.util.Enumeration;
import java.util.List;

import org.apache.commons.lang.StringUtils;
import org.hibernate.criterion.MatchMode;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Transactional;

import com.rbcs.base.item.service.ItemManager;
import com.rbcs.base.model.Item;
import com.rbcs.budget.model.Budget;
import com.rbcs.budget.model.BudgetItem;
import com.rbcs.budget.model.BudgetItemMonth;
import com.rbcs.budget.service.BudgetItemtManager;
import com.rbcs.budget.service.BudgetManager;
import com.rbcs.flow.FlowConstants;
import com.rbcs.flow.service.FlowManager;
import com.systop.common.modules.dept.model.Dept;
import com.systop.common.modules.dept.service.DeptManager;
import com.systop.common.modules.security.user.UserUtil;
import com.systop.common.modules.security.user.model.User;
import com.systop.core.ApplicationException;
import com.systop.core.Constants;
import com.systop.core.util.DateUtil;
import com.systop.core.webapp.struts2.action.DefaultCrudAction;

/**
 * 预算Action
 * 
 * @author Nice
 */
@SuppressWarnings("serial")
@Controller
@Scope(BeanDefinition.SCOPE_PROTOTYPE)
public class BudgetAcation extends DefaultCrudAction<Budget, BudgetManager> {

	@Autowired
	private BudgetItemtManager budgetItemtManager;

	@Autowired
	private ItemManager itemManager;

	@Autowired
	private FlowManager flowManager;

	@Autowired
	private DeptManager deptManger;

	// 科目月预算主键集合[BudgetItemMonth's id]
	private Integer[] bimIds;

	// 预算组成BudgetItem主键集合
	private Integer[] budgetItemIds;

	private Integer budgetYear;

	/**
	 * 部门预算全貌
	 * 
	 * @return
	 */
	public String deptBudgetAllIndex() {
		Dept dept = getLodinUserDept();
		String matchSn = MatchMode.START.toMatchString(dept.getSerialNo());
		String hql = "select b.year, sum(b.amount) from Budget b where b.dept.serialNo like ? and b.audStatus = ? group by (b.year)";
		items = getManager().query(hql, matchSn, FlowConstants.AUDIT_PASS);
		getRequest().setAttribute("dept", dept);
		return "deptBudgetAllIndex";
	}

	/**
	 * 上级部门查看下级部门的预算全貌，如果显示的下级部门的预算未0.0则代表预算为定制，或预算未通过审核
	 * 
	 * @return
	 */
	public String deptBudgetAllView() {
		Dept loginDept = getLodinUserDept();
		List<Item> budgetItems = itemManager.getByDeptSerialNo(loginDept
				.getSerialNo());

		String hqlDept = "from Dept d where d.serialNo like ? and d.isLeaf = ? order by d.serialNo";
		String matchSn = MatchMode.START.toMatchString(loginDept.getSerialNo());
		List<Dept> depts = deptManger.query(hqlDept, new Object[] { matchSn,
				Constants.YES });

		getRequest().setAttribute("budgetItems", budgetItems);
		getRequest().setAttribute("depts", depts);
		getRequest().setAttribute("loginDept", loginDept);
		return "deptBudgetAllView";
	}

	/**
	 * 财务查看的预算全面列表
	 * 
	 * @return
	 */
	public String financeBudgetAllIndex() {
		String hql = "select b.year, sum(b.amount) from Budget b where b.audStatus = ? group by (b.year)";
		items = getManager().query(hql, FlowConstants.AUDIT_PASS);
		return "financeBudgetAllIndex";
	}

	/**
	 * 财务查看单位的预算全貌
	 * 
	 * @return
	 */
	public String financeBudgetAllView() {
		List<Item> budgetItems = itemManager.getByDeptSerialNo("");
		String hqlDept = "from Dept d where d.isLeaf = ? order by d.serialNo";
		List<Dept> depts = deptManger.query(hqlDept, Constants.YES);
		getRequest().setAttribute("budgetItems", budgetItems);
		getRequest().setAttribute("depts", depts);
		return "financeBudgetAllView";
	}

	/**
	 * 查看本部门预算
	 * 
	 * @return
	 */
	public String deptIndex() {
		String hql = "from Budget b where b.dept.id = ? order by b.createTime desc";
		items = getManager().query(hql, getLodinUserDept().getId());
		return "deptIndex";
	}

	/**
	 * 新建预算
	 */
	public String editNew() {
		getModel().setDept(getLodinUserDept());
		String sn = DateUtil.getDateTime("yyyyMMdd", new Date());
		getModel().setSingleNo("YS-" + sn);
		getModel().setYear(Calendar.getInstance().get(Calendar.YEAR));
		if (getManager().getDao().exists(getModel(), "dept", "year")) {
			addActionError(getLodinUserDept() + "," + getModel().getYear()
					+ "年预算已存在");
		}
		return INPUT;
	}

	/**
	 * 预算详情编辑
	 */
	public String editDetail() {
		return "editDetail";
	}

	/**
	 * 预算详情查看
	 */
	public String view() {
		return VIEW;
	}

	/**
	 * 预算保存
	 */
	@SuppressWarnings("rawtypes")
	public String save() {
		try {
			getModel().setCreater(UserUtil.getLoginUser(getRequest()));
			getModel().setCreateTime(new Date());
			if (getManager().getDao().exists(getModel(), "singleNo")) {
				throw new ApplicationException("预算编号已存在："
						+ getModel().getSingleNo());
			}
			getManager().save(getModel());// 第一次保存
			Double amount = 0.0;
			// 获得参数
			Enumeration pNames = getRequest().getParameterNames();
			while (pNames.hasMoreElements()) {
				String pName = pNames.nextElement().toString();
				if (pName.indexOf("itemAmount_") != -1) {// 获得科目和预算额度
					String id = pName.substring("itemAmount_".length());// 科目ID
					BudgetItem bi = new BudgetItem();
					bi.setItem(getItem(Integer.valueOf(id)));
					bi.setAmount(Double.valueOf(getRequest()
							.getParameter(pName)));
					bi.setBudget(getModel());
					budgetItemtManager.splitSave(bi, getModel().getBtype());
					amount = amount + bi.getAmount();
				}
			}
			getModel().setAmount(amount);// 第二次保存
			getManager().save(getModel());
		} catch (ApplicationException e) {
			addActionError(e.getMessage());
			return INPUT;
		}
		return SUCCESS;
	}

	/**
	 * 更新预算
	 */
	@Transactional
	public String update() {
		if (bimIds != null) {
			for (Integer bimId : bimIds) {
				BudgetItemMonth bim = getBudgetItemMonth(bimId);
				setupData(bim);
				getManager().getDao().save(bim);
			}
		}
		getManager().countYearBudget(getModel());
		addActionMessage("数据修改成功,审核后生效");
		return "editDetail";
	}

	// 根据BudgetItemMonth's id组合参数名称，装填数据
	private void setupData(BudgetItemMonth bim) {
		if (bim == null || bim.getId() == null) {
			return;
		}
		Integer id = bim.getId();
		bim.setAmount(getDoubleValue("amount_", id));// 预算额
		bim.setAdd1th(getDoubleValue("add1th_", id));
		bim.setAdd2th(getDoubleValue("add2th_", id));
		bim.setAdd3th(getDoubleValue("add3th_", id));
		bim.setAdd4th(getDoubleValue("add4th_", id));
		bim.setFinalAmount(bim.getAmount() + bim.getAdd1th() + bim.getAdd2th()
				+ bim.getAdd3th() + bim.getAdd4th());
	}

	/**
	 * 删除预算
	 */
	public String remove() {
		getManager().remove(getModel());
		return "removeSuccess";
	}

	// 获得参数值，并转换成Double类型
	private Double getDoubleValue(String parmarPre, Integer id) {
		String doubleValue = getRequest().getParameter(parmarPre + id);
		if (StringUtils.isNotBlank(doubleValue)) {
			return Double.valueOf(doubleValue);
		}
		return 0.0;
	}

	/**
	 * 创建申请流程
	 * 
	 * @return
	 */
	public String createAudFlow() {
		if (getModel() != null && getModel().getId() != null) {
			String errorDepts = deptManger.checkManagerUser(getModel()
					.getDept().getSerialNo());
			if (StringUtils.isBlank(errorDepts)) {
				flowManager.createBudgetFlow(getModel());
				// 修改原始单据为待审状态
				getModel().setAudStatus(FlowConstants.AUDIT_PENDING);
				getManager().save(getModel());
			} else {
				throw new ApplicationException("操作失败,以下部门无负责人：" + errorDepts);
			}
		}
		return "createFlowSuccess";
	}

	// 获得科目
	private Item getItem(Integer id) {
		return getManager().getDao().get(Item.class, id);
	}

	// 获得BudgetItemMonth
	private BudgetItemMonth getBudgetItemMonth(Integer id) {
		return getManager().getDao().get(BudgetItemMonth.class, id);
	}

	// 获得关联部门
	private Dept getLodinUserDept() {
		User user = UserUtil.getLoginUser(getRequest());
		user = getManager().getDao().get(User.class, user.getId());
		return user.getDept();
	}

	public Integer[] getBimIds() {
		return bimIds;
	}

	public void setBimIds(Integer[] bimIds) {
		this.bimIds = bimIds;
	}

	public Integer[] getBudgetItemIds() {
		return budgetItemIds;
	}

	public void setBudgetItemIds(Integer[] budgetItemIds) {
		this.budgetItemIds = budgetItemIds;
	}

	public Integer getBudgetYear() {
		return budgetYear;
	}

	public void setBudgetYear(Integer budgetYear) {
		this.budgetYear = budgetYear;
	}

}
